package com.mofum.scope.annotation.service.parser;

import com.mofum.scope.annotation.service.ColumnScope;
import com.mofum.scope.common.annotation.AnnotationParser;
import com.mofum.scope.common.annotation.metadata.service.MColumnScope;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yuyang@qxy37.com
 * @since 2019-03-20
 **/
public class ColumnScopeParser<T> implements AnnotationParser<Class<T>, MColumnScope> {

    public Map<Field, MColumnScope> parseField(Class<T> tClass) {

        Map<Field, MColumnScope> map = new HashMap<Field, MColumnScope>();

        Field[] fields = tClass.getDeclaredFields();

        for (Field field : fields) {

            if (field.isAnnotationPresent(ColumnScope.class)) {

                ColumnScope atColumn = field.getAnnotation(ColumnScope.class);

                map.put(field, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Type, MColumnScope> parseType(Class<T> tClass) {

        Map<Type, MColumnScope> map = new HashMap<Type, MColumnScope>();

        Class<?> clazz = tClass;

        if (clazz.isAnnotationPresent(ColumnScope.class)) {

            ColumnScope atColumn = clazz.getAnnotation(ColumnScope.class);

            map.put(clazz, parse(atColumn));

        }

        return map;
    }

    public Map<Method, MColumnScope> parseMethod(Class<T> tClass) {

        Map<Method, MColumnScope> map = new HashMap<Method, MColumnScope>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            if (method.isAnnotationPresent(ColumnScope.class)) {

                ColumnScope atColumn = method.getAnnotation(ColumnScope.class);

                map.put(method, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Method, List<MColumnScope>> parseParams(Class<T> tClass) {

        Map<Method, List<MColumnScope>> map = new HashMap<Method, List<MColumnScope>>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            List<MColumnScope> list = new ArrayList<MColumnScope>();

            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof ColumnScope) {
                        ColumnScope atColumn = (ColumnScope) annotation;
                        list.add(parse(atColumn));
                    }
                }
            }

            map.put(method, list);
        }

        return map;
    }

    public MColumnScope parse(ColumnScope columnScope) {
        MColumnScope mColumnScope = new MColumnScope();
        mColumnScope.setName(columnScope.value());
        mColumnScope.setType(columnScope.type());
        mColumnScope.setTableName(columnScope.tableName());
        return mColumnScope;
    }

}

